﻿using System;
using System.Web;
using System.Web.Security;

using netaddICTs.Umb.ProtectedMedia.Business.Configuration;
using netaddICTs.Umb.ProtectedMedia.Business.IO;

using umbraco.BusinessLogic;
using umbraco.cms.businesslogic.member;

namespace netaddICTs.Umb.ProtectedMedia.Web {
    
    public partial class Download : System.Web.UI.Page {

        private readonly Business.Configuration.ProtectedMedia _cfg = Business.Configuration.ProtectedMedia.Instance;

        protected void Page_Load(object sender, EventArgs e)
        {
            if (Page.IsPostBack) return;

            var mediaId = Request.QueryString[Constants.IdQsKey];
            var hash = Request.QueryString[Constants.HashCodeQsKey];
            var isInternalDownload = new Business.Encryption.Library().IsInternalDownloadSHA1Ok(mediaId, hash);

            //If request to download is initiated from admin backend
            if (isInternalDownload) DownloadFile(int.Parse(mediaId));

            var isSHA1Ok = new Business.Encryption.Library().IsSHA1Ok(mediaId, hash);
            if (!isSHA1Ok)
                Redirect(Business.Configuration.ProtectedMedia.Instance.Nodes.Error.UmbracoNodeId);

            var currentMember = Member.GetCurrentMember();
            if (currentMember == null)
                Redirect(Business.Configuration.ProtectedMedia.Instance.Nodes.Login.UmbracoNodeId, XsltExtensions.Library.GetDownloadLink(int.Parse(mediaId)));

            if (!XsltExtensions.Library.HasPermissionToDownload(int.Parse(mediaId), currentMember))
                Redirect(Business.Configuration.ProtectedMedia.Instance.Nodes.NoAccess.UmbracoNodeId);

            DownloadFile(int.Parse(mediaId));
        }

        private void DownloadFile(int mediaNodeId)
        {

            try
            {
                //throws ArgumentException if media node id does not exist in umbracoNode table
                var mediaItem = new umbraco.cms.businesslogic.media.Media(mediaNodeId);

                //Check media node id
                if (mediaItem.Id != mediaNodeId) return;

                var fileStorageImpl = FileStorageFactory.GetFileStorageImplementation();
                var shortFilename = mediaItem.getProperty(_cfg.Aliases.InternalFileAlias.UmbracoAlias).Value.ToString();
                var filename = fileStorageImpl.BuildFilename(mediaNodeId, shortFilename);

                Response.Clear();
                Response.AddHeader("Content-Disposition", "attachment; filename=" + shortFilename.Replace(" ", "-"));
                Response.AddHeader("Content-Length", fileStorageImpl.CalculateBytes(filename).ToString());
                Response.ContentType = "application/octet-stream";

                Response.WriteFile(filename);
                Response.End();

            }
            catch
            {
                Log.Add(LogTypes.Error, umbraco.BusinessLogic.User.GetUser(0), mediaNodeId, string.Format("[ProtectedMedia]No media item exist with node id = {0}", mediaNodeId));
            }
        }

        private void Redirect(int nodeId)
        {
            Redirect(nodeId, string.Empty);
        }

        private void Redirect(int nodeId, string querystring)
        {
            var url = umbraco.library.NiceUrl(nodeId);
            if (!string.IsNullOrEmpty(querystring))
                url += ("?ReturnUrl=" + HttpUtility.UrlEncode(querystring));

            Response.Redirect(url, true);
        }
    }
}
